// Furious Tourist by Chris Dickinson
#pragma once

// uncomment this to show state colors on objects. Blue = asleep. Red = deactivated.
//#define _SHOWSTATECOLORS

#include "Physics/PhysicsEngine.h"
#include "FuriousTouristGlobals.h"
#include "d3dapplication.h"
#include "d3dUtil.h"
#include "DirectInput.h"
#include "MenuButton.h"
#include "Sphere.h"
#include "Box.h"
#include <vector>
#include "GameObject.h"
#include "HealthManager.h"
#include "ObjectTypes.h"
#include "MeshManager.h"
#include "Sprite.h"
#include "ParticleEffect.h"
#include "SoundManager.h"
#include "FloatingTextManager.h"

// needed by FontDesc
#include <windows.h>
#include <tchar.h>

// needed for playing movies
#include "dshow.h"

enum GameState {
	GAMESTATE_INTRO,
	GAMESTATE_MENU,
	GAMESTATE_LEVELSELECT,
	GAMESTATE_CREDITS,
	GAMESTATE_OPTIONS,
	GAMESTATE_PLAY,
	GAMESTATE_END,
	GAMESTATE_HELP,
	GAMESTATE_QUIT
};

enum ProjectileState {
	PROJECTILESTATE_READY,
	PROJECTILESTATE_PREPARED,
	PROJECTILESTATE_INFLIGHT,
	PROJECTILESTATE_WAITING
};

enum ButtonID {
	BUTTON_PLAY,
	BUTTON_HELP,
	BUTTON_CREDITS,
	BUTTON_OPTIONS,
	BUTTON_BACK,
	BUTTON_SOUNDUP,
	BUTTON_SOUNDDOWN,
	BUTTON_MUSICUP,
	BUTTON_MUSICDOWN,
	BUTTON_WINDOWED,
	BUTTON_FULLSCREEN,
	BUTTON_CONTROLS,
	BUTTON_QUIT,
	BUTTON_RESET,
	BUTTON_MENU,
	BUTTON_TOGGLEHEALTH,
	BUTTON_NEXTLEVEL,
	BUTTON_RETRYLEVEL,
	BUTTON_BACKTOMENU,
	BUTTON_NEXTHELP,
	BUTTON_PREVHELP,
	BUTTON_DONEHELP,
	BUTTON_LEVELSTART,
	BUTTON_LEVEL1,
	BUTTON_LEVEL2,
	BUTTON_LEVEL3,
	BUTTON_LEVEL4,
	BUTTON_LEVEL5,
	BUTTON_LEVEL6,
	BUTTON_LEVEL7,
	BUTTON_LEVEL8,
	BUTTON_LEVEL9,
	BUTTON_LEVEL10,
	BUTTON_LEVEL11,
	BUTTON_LEVEL12,
	BUTTON_LEVEL13,
	BUTTON_LEVEL14,
	BUTTON_LEVEL15,
	BUTTON_LEVEL16,
	BUTTON_LEVEL17,
	BUTTON_LEVEL18,
	BUTTON_LEVEL19,
	BUTTON_LEVEL20,
	BUTTON_LEVELEND
};

enum SoundID
{
	SOUND_WOODIMPACT,
	SOUND_WOODBREAK,
	SOUND_STONEIMPACT,
	SOUND_STONEBREAK,
	SOUND_BLACKBIRDDEATH,
	SOUND_SEAGULLDEATH,
	SOUND_PARROTDEATH,
	SOUND_TOUCANDEATH,
	SOUND_BIRDSQUAWK,
	SOUND_EXPLOSION,
	SOUND_POP,
	SOUND_PROJECTILELOAD,
	SOUND_PROJECTILEPREPARE,
	SOUND_PROJECTILERELEASE,
	SOUND_ROCKETNUTLAUNCH,
	SOUND_MULTINUTSPLIT,
	SOUND_MENUCLICK1,
	SOUND_MENUCLICK2,
	SOUND_MENUERROR,
	SOUND_WIN,
	SOUND_LOSE,
	SOUND_BRONZEDING,
	SOUND_SILVERDING,
	SOUND_GOLDDING,
	SOUND_COCONUTIMPACT,
	SOUND_BEACHAMBIENCE,
	SOUND_AMBIENTRANDOM1,
	SOUND_AMBIENTRANDOM2,
	SOUND_AMBIENTRANDOM3,
	SOUND_AMBIENTRANDOM4,
	SOUND_AMBIENTRANDOM5,
	SOUND_AMBIENTRANDOM6,
	SOUND_AMBIENTRANDOM7,
	SOUND_AMBIENTRANDOM8,
	SOUND_AMBIENTRANDOM9
};

enum MusicID
{
	MUSIC_TITLE
};

class FuriousTourist 
: 
public d3dapplication,
public physics::PhysicsEngine
{
	// typedefs for ease of readability
	typedef std::vector<MenuButton*>			Buttons;
	typedef std::vector<GameObject*>			GameObjects;
	typedef std::vector<Sphere*>				Markers;
	typedef std::vector<ParticleEffect*>		Particles;
	typedef std::vector<IDirect3DTexture9*>		HelpScreens;

public:
	FuriousTourist(HINSTANCE hInstance, std::string caption, D3DDEVTYPE devType, DWORD requestedVP);
	~FuriousTourist();

	// overriding the base class virtual functions
	// these are blank in the base class (since it doesn't do anything
	// but initialize devices), so we need to define their behaviour here
	bool checkDeviceCaps();
	void OnLostDevice();
	void OnResetDevice();
	void Update(float dt);
	void Render();

	void LoadAssets(void);
	void CreateGameAssets(void);
	void DestroyGameAssets(void);
	void CreateAsset(physics::CollisionPrimitive *primitive, GameObject *object);
	void DestroyAsset(physics::RigidBody *body);
	void InitializeFX(void);

	void CreateLevelSelectButtons(void);
	void DeleteButtons(Buttons &buttonList);

	void UpdateGame(float dt);
	void UpdateMenu(float dt);
	void UpdateLevelSelect(float dt);
	void UpdateCredits(float dt);
	void UpdateOptions(float dt);
	void UpdateHelp(float dt);
	void UpdateFPS(float dt);

	void RenderMenu(void);
	void MoveTitleGraphic(float dt);
	void RenderCredits(void);
	void RenderHelp(void);
	void RenderOptions(void);
	void RenderFPS(void);
	void RenderHUD(void);
	void RenderHelpHUD(void);
	void RenderEndGameScoreHUD(void);
	void RenderGame(void);
	void RenderLevelSelect(void);
	void RenderBackground(void);
	void RenderRopes(void);
	void RenderTitleGraphics(void);

	void IncreaseVolume(float &v);
	void DecreaseVolume(float &v);

	void InitGame(void);

	void LoadMap(char* name);
	int GetUnlockedLevel(void);
	void ReplaceUnlockedLevel(int level);
	int GetHighScore();
	void SaveHighScore();

	void PlayIntroMovie(void);

	void SetProjectile(GameObject *object);
	void ClearFirstWeapon(void);
	bool LoadNextWeapon(void);
	void GenerateExplosion(physics::Vector3 detonation);
	void CreateMarker(void);
	void ClearAllMarkers(void);
	void ClearPreviousMarkers(void);

	void LaunchProjectile(float dt);

	void CheckAmbientSound(float dt);

	void InitializeProjectionMatrix(void);
	void UpdateViewMatrix(float dt);

	D3DXVECTOR3 GetWorldPickingRay();
	D3DXVECTOR3 GetScreenPosition(D3DXVECTOR3 position);

	void DebugInfo(void);

private:
	// keeps track of the game state
	GameState		mState;
	// determines whether to show FPS or not
	// and how many frames have run
	bool			mShowFPS;
	float			mFPS;

	// keeping track of the windowed/fullscreen state
	bool			mWindowed;

	// D3DX that the game needs to do stuff with
	ID3DXSprite*		mpD3DSprite;
	ID3DXFont*			mpD3DMenuFont;
	ID3DXFont*			mpD3DSmallMenuFont;
	ID3DXFont*			mpD3DSmallFont;
	ID3DXFont*			mpD3DLargeFont;

	// menu buttons
	Buttons				mMainMenuButtons;
	Buttons				mHelpButtons;
	Buttons				mCreditsButtons;
	Buttons				mLevelSelectButtons;
	Buttons				mOptionsButtons;
	Buttons				mGameButtons;
	Buttons				mInGameHelpButtons;
	Buttons				mWinLoseScreenButtons;

	// textures for the title
	IDirect3DTexture9*	mMenuBackgroundTex;
	IDirect3DTexture9*  mMenuTitleTex;
	IDirect3DTexture9*  mTouristTitleTex;
	D3DXVECTOR3			mMenuTitlePosition;
	float				mMenuTitleRot;
	float				mMenuTitleLen;	

	// volume
	float				mSoundVolume;
	float				mMusicVolume;

	// Movie objects
	IGraphBuilder*		mpGraphBuilder;
	IMediaControl*		mpMediaControl;
	IMediaEvent*		mpMediaEvent;
	IVideoWindow*		mpVideoWindow;

	// particle effects
	//ParticleEffect			*mExplosionEffect;
	Particles					mParticles;

	// important game objects
	GameObjects					mGameObjects;
	GameObjects					mWeapons;
	GameObject*					mProjectile;		// pointer to the current projectile
	ProjectileState				mProjectileState;	// current state of the projectile/round/game
	Markers						mMarkerSet1;
	Markers						mMarkerSet2;
	Markers						*mpCurrentMarkers;
	HelpScreens					mHelpScreens;
	
	// mouse button variables and control system
	bool						mLaunchOnRelease;
	bool						mButtonDown;
	bool						mButtonReady;
	bool						mButtonReleased;
	
	// game values
	unsigned short int			mNumBirdsLeft;
	float						mEndGameTimer;
	bool						mEndGameCount;
	float						mTimeElapsedSinceCollision;
	float						mTimeElapsedSinceCreatedLastMarker;
	bool						mWaitCount;
	int							mCurrentLevel;
	IDirect3DTexture9*			mBackdrop;
	bool						mSpecialUsed;
	int							mUnlockedLevel;
	bool						mPlaySquawk;
	bool						mDisplayWinScreen;
	bool						mBeginWinScreenDelay;
	float						mTimeElapsedSinceWin;
	float						mTimeElapsedSinceShowScore;
	bool						mDisplayLoseScreen;
	bool						mDisplayInGameHelp;
	IDirect3DTexture9*			mWinLoseScreenTex;
	int							mCurrentHelpScreen;
	unsigned int				mScore;
	float						mAmbientTriggerTime;
	bool						mCameraMoving;
	int							mSpareWeapons;
	physics::Vector3			mCatapultPosition;
	physics::Vector3			mProjectileStartPosition;
	bool						mShowHealth;
	IDirect3DTexture9*			mWinTouristTex;
	IDirect3DTexture9*			mLoseTouristTex;
	IDirect3DTexture9*			mStarTex;
	bool						mPlayedBronzeDing;
	bool						mPlayedSilverDing;
	bool						mPlayedGoldDing;
	bool						mGameOver;

	// screen barriers
	float mBarrierLeft;
	float mBarrierRoof;
	float mBarrierRight;
	float mBarrierGround;

	// debug values

	// force generators
	physics::Gravity *mForceDueToGravity;
	physics::Explosion *mExplosiveForce;
	bool mStopExplosion;

	// effect info
	ID3DXEffect* mFX;
	D3DXHANDLE   mhTech;
	D3DXHANDLE   mhWorld;
	D3DXHANDLE   mhWorldInvTrans;
	D3DXHANDLE   mhWVP;
	D3DXHANDLE   mhAmbientMtrl;
	D3DXHANDLE   mhAmbientLight;
	D3DXHANDLE   mhDiffuseMtrl;
	D3DXHANDLE   mhDiffuseLight;
	D3DXHANDLE   mhSpecMtrl;
	D3DXHANDLE   mhSpecLight;
	D3DXHANDLE   mhSpecPower;
	D3DXHANDLE   mhLightVecW;
	D3DXHANDLE   mhEyePos;
	D3DXHANDLE   mhTex;

	// lighting info
	D3DXCOLOR	mAmbientLight;
	D3DXCOLOR	mDiffuseLight;
	D3DXCOLOR	mSpecLight;
	D3DXVECTOR3	mLightVecW;
	D3DXVECTOR3	mAttenuation012;

	// camera info
	float mCameraRotationY;
	float mCameraRadius;
	float mCameraPosX;
	float mCameraPosY;
	float mCameraPosZ;

	// important matrices
	D3DXMATRIX mWorld;		// world matrix
	D3DXMATRIX mView;		// view matrix
	D3DXMATRIX mProj;		// projection matrix

	// renderinfo which stores all of the important rendering info
	// we need to pass into our objects later
	RenderInfo mRenderInfo;
};
